<?php
namespace Project_725\Controller;

use Project_725\FC_Frontend;
use Project_725\FC_ApiExcep;
use TwinPeaks\Core as Core;
use Project_725\Model as Model;
use Project_725\Model\User;
use Project_725\Lib as Lib;
use Project_725\Lib\Mailer;

class API extends Core\CController
{
	/**
	 * @return Model\User
	 */
	private function getUserByAccessToken($token)
	{
		$user = Model\User::getByAccessToken($token);
		if ($user == null)
			FC_ApiExcep::invalidAccessToken($token)->_throw();

		return $user;
	}

	/**
	 * Invite user
	 * 
	 * @return
	 */
	function invite()
	{
		$filter = $this->getFilter();		
		$sender = $this->getUserByAccessToken($filter->getAccessToken());
		$senderId = $sender->getId();
		
		$inviteCode = Model\Invitation::generateCode();		
		$email = $filter->getEmail();
		$defaultPass = null;
		
		// Figure out whether user account with given email exists.
		// If account does not exist sign up user for the service.
		$recipient = Model\User::getByEmail($email);
		if (!$recipient)
		{
			$defaultPass = Model\User::generateDefaultPass();
			// We assume that recipient has opposite to the sender sex.
			// We don't care about gay couples. Gay is bad, m'okay.
			if ($sender->isFemale())
				$sex = User::SEX_MALE;
			else
				$sex = User::SEX_FEMALE;
			
			$recipientId = Model\User::autoSignup($email, $defaultPass, $sex, $senderId);
		}
		else
			$recipientId = $recipient->getId();

		$invite = Model\Invitation::create($senderId, $recipientId,
			$filter->getSenderName(), $filter->getRecipientName(), $inviteCode);
		
		$mailer = Lib\Mailer::getInstance();
		$mailer->processInvitation($email, $defaultPass, $invite);
	}
	
	/**
	 * @return array|false
	 */
	function saveLocation()
	{
		$filter = $this->getFilter();
		
		$user = $this->getUserByAccessToken($filter->getAccessToken());
		
		$user->setLocLat($filter->getLat());
		$user->setLocLong($filter->getLong());
		$user->setLocUpdateTime(new \DateTime('now'));
        $user->save();

		$pairedId = $user->getPairedUserId();
		if (!$pairedId)
			FC_ApiExcep::noPairedUser()->_throw();
		
		$paired = Model\User::getById($pairedId);
		if ($paired->isSuspended())
			FC_ApiExcep::accountSuspended()->_throw();
		
		$pairedLat = $paired->getLocLat();
		$pairedLong = $paired->getLocLong();
		if (!$pairedLat || !$pairedLong)
			FC_ApiExcep::pairedUnknownLoc()->_throw();
		
		$distance = Lib\calc_distance($user->getLocLat(), $user->getLocLong(),
			$pairedLat, $pairedLong);
		
		return ['distance'  => $distance];
	}
	
	/**
	 * @return boolean
	 */
	function ping()
	{
		return true;
	}
	
	/**
	 * @return
	 */
	function signup()
	{
		$filter = $this->getFilter();
		
		$email = $filter->getEmail();
		$pass = $filter->getPass();
		$sex = $filter->getSex();
		
		if (Model\User::accountExists($email))
			FC_ApiExcep::accountExists($email)->_throw();

		$confirmCode = Core\get_unique_id();
		Model\User::signUp($email, $pass, $sex, $confirmCode);
		
		$mailer = Lib\Mailer::getInstance();
		$mailer->processSignup($email, $pass, $confirmCode);
	}
	
	/**
	 * Returns new access token
	 * 
	 * @return array
	 */
	function getAccessToken()
	{
		$filter = $this->getFilter();
		
		$user = Model\User::getByLogin($filter->getLogin());		
		if (!$user)
			FC_ApiExcep::wrongCredentials()->_throw();
		
		if (!$user->checkPass($filter->getPass()))
			FC_ApiExcep::wrongCredentials()->_throw();
		
		$token = Model\User::generateAccessToken();
		$user->setAccessToken($token);
		$user->save();

		return ['access-token' => $token];
	}
	
	/**
	 * @return
	 */
	function getStatusInfo()
	{
		$filter = $this->getFilter();
		$user = $this->getUserByAccessToken($filter->getAccessToken());
		
		$info = [];
		
		$info['invite'] = [];
		$myInvites = Model\Invitation::getBySenderId($user->getId());
		foreach ($myInvites as $invite)
		{
			$info['invites'] = [
				'code' => $invite->getCode(),
				'recipient_name' => $invite->getRecipientName(),
				'status' => $invite->getStatus()
			];
		}
		return $info;
	}
	
	/**
	 * @return
	 */
	function withdrawInvitation()
	{
		$filter = $this->getFilter();
		$user = $this->getUserByAccessToken($filter->getAccessToken());
		
		$invite = Model\Invitation::getByCode($filter->getInviteCode());
		if (!$invite)
			return true;
		
		if ($invite->getSenderId() != $user->getId())
			return false;
		
		Mailer::getInstance()->processInviteWithdrawal($invite);
		//$invite->delete();
	}
}
